﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Netnr.DataKit.Func
{
    public class DK
    {
        /// <summary>
        /// 获取所有表名及注释
        /// </summary>
        /// <param name="tdb">数据库类型（0：MySQL，1：SQLite，2：Oracle，3：SQLServer，4：PostgreSQL）</param>
        /// <param name="conn">连接字符串</param>
        /// <returns></returns>
        public ActionResultVM GetTable(DB.TypeDB? tdb, string conn)
        {
            var vm = new ActionResultVM();

            try
            {
                var tvm = ForTypeDBSetConn(tdb, conn);

                if (tvm.code == 200)
                {
                    switch (tdb)
                    {
                        case DB.TypeDB.MySQL:
                            vm.data = new DataKit.DK.DataKitMySQL().GetTable();
                            break;
                        case DB.TypeDB.SQLite:
                            vm.data = new DataKit.DK.DataKitSQLite().GetTable();
                            break;
                        case DB.TypeDB.Oracle:
                            vm.data = new DataKit.DK.DataKitOracle().GetTable();
                            break;
                        case DB.TypeDB.SQLServer:
                            vm.data = new DataKit.DK.DataKitSQLServer().GetTable();
                            break;
                        case DB.TypeDB.PostgreSQL:
                            vm.data = new DataKit.DK.DataKitPostgreSQL().GetTable();
                            break;
                    }

                    vm.Set(ARTag.success);
                }
                else
                {
                    vm = tvm;
                }
            }
            catch (Exception ex)
            {
                vm.Set(ex);
            }

            return vm;
        }

        /// <summary>
        /// 获取所有列
        /// </summary>
        /// <param name="tdb">数据库类型（0：MySQL，1：SQLite，2：Oracle，3：SQLServer，4：PostgreSQL）</param>
        /// <param name="conn">连接字符串</param>
        /// <param name="filterTableName">过滤表名，英文逗号分隔，为空时默认所有表</param>
        /// <returns></returns>
        public ActionResultVM GetColumn(DB.TypeDB? tdb, string conn, string filterTableName = "")
        {
            var vm = new ActionResultVM();

            try
            {
                var listTableName = new List<string>();
                if (!string.IsNullOrWhiteSpace(filterTableName))
                {
                    listTableName = filterTableName.Split(',').ToList();
                }
                else
                {
                    listTableName = null;
                }

                var tvm = ForTypeDBSetConn(tdb, conn);
                if (tvm.code == 200)
                {
                    switch (tdb)
                    {
                        case DB.TypeDB.MySQL:
                            vm.data = new DataKit.DK.DataKitMySQL().GetColumn(listTableName);
                            break;
                        case DB.TypeDB.SQLite:
                            vm.data = new DataKit.DK.DataKitSQLite().GetColumn(listTableName);
                            break;
                        case DB.TypeDB.Oracle:
                            vm.data = new DataKit.DK.DataKitOracle().GetColumn(listTableName);
                            break;
                        case DB.TypeDB.SQLServer:
                            vm.data = new DataKit.DK.DataKitSQLServer().GetColumn(listTableName);
                            break;
                        case DB.TypeDB.PostgreSQL:
                            vm.data = new DataKit.DK.DataKitPostgreSQL().GetColumn(listTableName);
                            break;
                    }

                    vm.Set(ARTag.success);
                }
                else
                {
                    vm = tvm;
                }
            }
            catch (Exception ex)
            {
                vm.Set(ex);
            }

            return vm;
        }

        /// <summary>
        /// 赋值
        /// </summary>
        /// <param name="tdb"></param>
        /// <param name="conn"></param>
        private ActionResultVM ForTypeDBSetConn(DB.TypeDB? tdb, string conn)
        {
            var vm = new ActionResultVM();

            if (tdb == null)
            {
                vm.Set(ARTag.lack);
                vm.msg = "数据库类型不能为空";
            }
            else if (string.IsNullOrWhiteSpace(conn))
            {
                vm.Set(ARTag.lack);
                vm.msg = "连接字符串不能为空";
            }
            else
            {
                switch (tdb)
                {
                    case DB.TypeDB.MySQL:
                        DB.MySQLDB.connectionString = conn;
                        break;
                    case DB.TypeDB.SQLite:
                        {
                            //下载 SQLite 文件
                            var ds = conn.Substring(12);
                            //路径
                            var dspath = AppContext.BaseDirectory + "tmp/";
                            if (!Directory.Exists(dspath))
                            {
                                Directory.CreateDirectory(dspath);
                            }
                            //文件名
                            var dsname = DateTime.Now.ToString("yyyyMMdd") + "_" + SHA128ToLong(ds) + ".db";

                            //网络路径
                            if (ds.ToLower().StartsWith("http"))
                            {
                                //不存在则下载
                                if (!File.Exists(dspath + dsname))
                                {
                                    //删除超过1天的下载文件
                                    var files = Directory.GetFiles(dspath);
                                    foreach (var file in files)
                                    {
                                        var ct = Path.GetFileName(file).Split('_')[0];
                                        if (ct.Length == 8)
                                        {
                                            if ((DateTime.Now - DateTime.Parse(ct.Insert(4, "-").Insert(7, "-"))).TotalDays >= 1)
                                            {
                                                File.Delete(file);
                                            }
                                        }
                                    }

                                    //下载
                                    new System.Net.WebClient().DownloadFile(ds, dspath + dsname);
                                }

                                DB.SQLiteDB.connectionString = "Data Source=" + dspath + dsname;
                            }
                            else if (File.Exists(ds))
                            {
                                DB.SQLiteDB.connectionString = "Data Source=" + ds;
                            }
                            else
                            {
                                vm.Set(ARTag.error);
                                vm.msg = "网络路径有误";

                                return vm;
                            }
                        }
                        break;
                    case DB.TypeDB.Oracle:
                        DB.OracleDB.connectionString = conn;
                        break;
                    case DB.TypeDB.SQLServer:
                        DB.SQLServerDB.connectionString = conn;
                        break;
                    case DB.TypeDB.PostgreSQL:
                        DB.PostgreSQLDB.connectionString = conn;
                        break;
                }

                vm.Set(ARTag.success);
            }

            return vm;
        }

        /// <summary>
        /// 设置表注释
        /// </summary>
        /// <param name="tdb">数据库类型（0：MySQL，1：SQLite，2：Oracle，3：SQLServer，4：PostgreSQL）</param>
        /// <param name="conn">连接字符串</param>
        /// <param name="TableName">表名</param>
        /// <param name="TableComment">表注释</param>
        /// <returns></returns>
        public ActionResultVM SetTableComment(DB.TypeDB? tdb, string conn, string TableName, string TableComment)
        {
            var vm = new ActionResultVM();

            try
            {
                var tvm = ForTypeDBSetConn(tdb, conn);

                if (tvm.code == 200)
                {
                    switch (tdb)
                    {
                        case DB.TypeDB.MySQL:
                            vm.data = new DataKit.DK.DataKitMySQL().SetTableComment(TableName, TableComment);
                            break;
                        case DB.TypeDB.SQLite:
                            vm.data = new DataKit.DK.DataKitSQLite().SetTableComment(TableName, TableComment);
                            break;
                        case DB.TypeDB.Oracle:
                            vm.data = new DataKit.DK.DataKitOracle().SetTableComment(TableName, TableComment);
                            break;
                        case DB.TypeDB.SQLServer:
                            vm.data = new DataKit.DK.DataKitSQLServer().SetTableComment(TableName, TableComment);
                            break;
                        case DB.TypeDB.PostgreSQL:
                            vm.data = new DataKit.DK.DataKitPostgreSQL().SetTableComment(TableName, TableComment);
                            break;
                    }

                    vm.Set(ARTag.success);
                }
                else
                {
                    vm = tvm;
                }
            }
            catch (Exception ex)
            {
                vm.Set(ex);
            }

            return vm;
        }

        /// <summary>
        /// 设置列注释
        /// </summary>
        /// <param name="tdb">数据库类型（0：MySQL，1：SQLite，2：Oracle，3：SQLServer，4：PostgreSQL）</param>
        /// <param name="conn">连接字符串</param>
        /// <param name="TableName">表名</param>
        /// <param name="FieldName">列名</param>
        /// <param name="FieldComment">列注释</param>
        /// <returns></returns>
        public ActionResultVM SetColumnComment(DB.TypeDB? tdb, string conn, string TableName, string FieldName, string FieldComment)
        {
            var vm = new ActionResultVM();

            try
            {
                var tvm = ForTypeDBSetConn(tdb, conn);

                if (tvm.code == 200)
                {
                    switch (tdb)
                    {
                        case DB.TypeDB.MySQL:
                            vm.data = new DataKit.DK.DataKitMySQL().SetColumnComment(TableName, FieldName, FieldComment);
                            break;
                        case DB.TypeDB.SQLite:
                            vm.data = new DataKit.DK.DataKitSQLite().SetColumnComment(TableName, FieldName, FieldComment);
                            break;
                        case DB.TypeDB.Oracle:
                            vm.data = new DataKit.DK.DataKitOracle().SetColumnComment(TableName, FieldName, FieldComment);
                            break;
                        case DB.TypeDB.SQLServer:
                            vm.data = new DataKit.DK.DataKitSQLServer().SetColumnComment(TableName, FieldName, FieldComment);
                            break;
                        case DB.TypeDB.PostgreSQL:
                            vm.data = new DataKit.DK.DataKitPostgreSQL().SetColumnComment(TableName, FieldName, FieldComment);
                            break;
                    }

                    vm.Set(ARTag.success);
                }
                else
                {
                    vm = tvm;
                }
            }
            catch (Exception ex)
            {
                vm.Set(ex);
            }

            return vm;
        }

        /// <summary>
        /// SHA1 加密 为 long
        /// </summary>
        /// <param name="str">内容</param>
        /// <returns></returns>
        private long SHA128ToLong(string str)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            using (SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider())
            {
                byte[] byteArr = SHA1.ComputeHash(buffer);
                return BitConverter.ToInt64(byteArr, 0);
            }
        }
    }
}
